package engine

import (
	"fmt"
	"time"

	"gitee.com/knowgo/gpa/engine/constants"
	"gitee.com/knowgo/gpa/engine/sql/dialects"
	"gitee.com/knowgo/gpa/engine/sql/dialects/dialect"
	"gitee.com/knowgo/gpa/engine/sql/metas/rflt"
	"gitee.com/knowgo/gpa/engine/sql/metas/schema"
	"gitee.com/knowgo/gpa/rt"
	"gitee.com/knowgo/logo"
	"gitee.com/knowgo/logo/log"
)

type Engine struct {
	provider    rt.Provider
	dialect     dialect.Dialect
	propsParser *rflt.PropsParser
	TZLocation  *time.Location // The timezone of the application
	DatabaseTZ  *time.Location // The timezone of the database
	logger      logo.Logger

	tablesInDatabase []*schema.Table
}

type Option struct {
	rt.Option
	DatabaseTZ *time.Location
}

func (e *Engine) GetProvider() *rt.Provider {
	return &e.provider
}

func New(dialectName constants.DIALECT, source string, opt *Option) (e *Engine, err error) {
	if opt == nil {
		opt = &Option{}
	}
	if opt.DatabaseTZ == nil {
		opt.DatabaseTZ = time.Local
	}
	if opt.Logger == nil {
		opt.Logger = log.GetDefaultLogger()
	}
	driver := dialectName.GetDRIVER()
	if driver == constants.DB_UNKNOWN {
		return nil, fmt.Errorf("unkown databse driver of dialect %s", dialectName)
	}
	dial, err := dialects.OpenDialect(dialectName, source)
	if err != nil {
		return nil, err
	}

	propsParser := rflt.NewPropsParser(dial)
	prvd, err := rt.NewProvider(dialectName, source, &opt.Option)
	if err != nil {
		return nil, err
	}
	e = &Engine{
		provider:    *prvd,
		dialect:     dial,
		propsParser: propsParser,
		DatabaseTZ:  opt.DatabaseTZ,
		logger:      opt.Logger,
	}
	return
}
